package zk

import (
	"doveclient/config"
	"fmt"
	"net"
	"os"
	"regexp"
	"strings"
	"time"
)

var monitorNodeRoot string

// ConfigNameToPath
func CN2P(name string) string {
	path := config.GetZkConfig()["root"].(string)
	if name != "" && name != "/" {
		path += "/" + strings.Replace(name, ".", "/", -1)
		path = strings.TrimRight(path, "/")
	}
	return path
}

// PathToConfigName
func P2CN(path string) string {
	name := strings.TrimPrefix(path, strings.TrimRight(config.GetZkConfig()["root"].(string), "/")+"/")
	name = strings.Replace(strings.Trim(name, "/"), "/", ".", -1)
	return name
}

func MyMonitorNode() (string, error) {
	if monitorNodeRoot != "" {
		return monitorNodeRoot, nil
	}

	hostName, err := os.Hostname()
	if err != nil {
		return "unkown hostname", err
	}
	conn, err := net.DialTimeout("tcp", GetOneHost(), time.Second*7)
	if err != nil {
		return "", err
	}
	localAddr := strings.Split(conn.LocalAddr().String(), ":")
	monitorNodeRoot = MonitorNodeRoot() + "/" + hostName + ":" + fmt.Sprintf("%v@%v:%v", localAddr[0], os.Getpid(), config.GetConfig().ClientVer)
	return monitorNodeRoot, nil
}

func MonitorNodeRoot() string {
	return config.GetZkConfig()["root"].(string) + "_monitor"
}

func MonitorNode(listenAddr string) (string, error) {
	if match, err := regexp.MatchString("^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}:[0-9]{1,5}$", listenAddr); err != nil || !match {
		return "", nil
	}

	addrSlice := strings.Split(listenAddr, ":")
	ip := net.ParseIP(addrSlice[0])
	if !ip.IsLoopback() && addrSlice[0] != "0.0.0.0" {
		return "_monitor_instance_run." + listenAddr, nil
	}

	addrs, err := net.InterfaceAddrs()
	if err != nil {
		return "", nil
	}

	var ipaddr string
	for _, addr := range addrs {
		if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
			if ipnet.IP.To4() != nil {
				ipaddr = ipnet.IP.String()
				break
			}
		}
	}

	if ipaddr == "" {
		return "", nil
	}

	return "_monitor_instance_run." + ipaddr + ":" + addrSlice[1], nil
}
